# -*- coding:utf-8 -*-
# file_name      vip_video_final.py
import tkinter as tk  # 导入 tkinter 模块用于创建 GUI，别名为 tk
import webbrowser  # 导入 webbrowser 模块，用于在程序中打开网页，调用用户系统默认浏览器
from tkinter import ttk  # 从 tkinter 模块导入 ttk，用于使用 ttk 主题和组件，使得Tk界面看起来更加美观和现代化
from tkinter.messagebox import showwarning # 从 tkinter.messagebox 模块导入 showwarning，用于显示警告消息框

from pynput import mouse
import os
import subprocess#接口执行外部命令和脚本
import requests  # 导入 requests 模块，用于发送 HTTP 请求和获取响应，像web服务器发送请求
from bs4 import BeautifulSoup # 导入 BeautifulSoup 模块，用于解析 HTML 或 XML 文档

# 初始化一个空列表和一个空字典
txt_list = []
mapping = dict()


def center_window(window, w, h):
    ws = window.winfo_screenwidth()  # 获取屏幕宽度和高度
    hs = window.winfo_screenheight()
    x = (ws / 2) - (w / 2)  # 计算窗口在屏幕上的中心位置
    y = (hs / 2) - (h / 2)
    window.geometry('%dx%d+%d+%d' % (w, h, x, y))  # 设置窗口的新尺寸和位置


def do_search():
    """
    执行搜索操作。
    根据用户输入的搜索条件，在指定的网站上进行搜索，并将搜索结果展示在一个下拉框（cbox）中。
    根据搜索类型（链接或关键词），会调用不同的搜索函数来获取结果。
    """
    # 处理用户输入的搜索参数和操作类型
    search_text = search_v.get().strip()  # 搜索文本
    query_site = site_v.get().strip()  # 查询网站
    query = query_v.get().strip()  # 查询条件
    op_value = op_v.get().strip()  # 操作类型（链接或关键词）

    if op_value == 'link':
        # 链接类型搜索处理
        full_url = f'{query_site}?url={query}'  # 构造完整URL
        cbox.set(full_url)  # 在下拉框中展示URL
        print(f'full_url')
    else:
        # 关键词类型搜索处理
        print(f'query_site={query_site}, search_text={search_text}')
        # 根据搜索类型调用不同的搜索函数
        if search_text == '1':
            fetch_teleplay_url(query, query_site)  # 电视剧搜索
        elif search_text == '2':
            fetch_movie_url(query, query_site)  # 电影搜索
        else:
            # 默认为综艺搜索
            fetch_tv_show_url(query, query_site)

        # 更新下拉框以显示搜索结果，并设置默认选中项
        cbox['value'] = txt_list  # 设置下拉框选项为搜索结果
        if len(txt_list) > 0:
            cbox.set(txt_list[0])  # 如果有结果，设置默认选中项为第一个结果
        else:
            # 没有找到搜索结果时的处理
            showwarning('搜索结果', f'未找到{query}对应的电视剧，请尝试使用链接解析')


def play_video():
    # ...（原有逻辑不变）

    if op_v.get().strip() == 'link':
        select_items = cbox.get()
        webbrowser.open(select_items)


    else:  # 如果用户选择的是内置播放

        select_items = cbox.get()  # 获取用户选择的视频

        print(f'select_items={select_items}')  # 打印用户选择的视频信息

        # 检查是否选择了线路二（PotPlayer）

        if site_v.get().strip() == r'D:\Program Files (x86)\PotPlayer\PotPlayerMini64.exe':

            # 构造命令来调用PotPlayer播放视频链接

            video_url = mapping.get(select_items)  # 从映射表中获取视频播放链接

            if video_url:

                # 注意：确保URL被安全处理，避免安全风险

                cmd = [site_v.get(), '/new', video_url]  # 使用'/new'参数在一个新窗口中打开视频

                try:

                    subprocess.Popen(cmd, shell=True) # 尝试启动PotPlayer进程来播放视频

                except Exception as e:

                    print(f"Error starting PotPlayer: {e}")

            else:

                print("No URL found for selected item.")

        else:

            # 其他线路的处理逻辑保持不变

            play_url = mapping[select_items]

            webbrowser.open(play_url)


def fetch_teleplay_url(query, line=None):
    """
    该函数用于根据指定的查询关键词在腾讯视频网站上搜索电视剧，并获取剧集的播放链接。

    参数:
    - query: str, 搜索的关键词，用于在腾讯视频上查找电视剧。
    - line: str, 可选参数，表示电视剧的播放线路，可以为空。

    返回值:
    无。该函数通过更新全局变量 `txt_list` 和 `mapping` 来存储结果。
    - `txt_list`: 列表，存储每个剧集的标题。
    - `mapping`: 字典，键为剧集标题，值为对应的播放链接。

    注意:
    - 函数首先清空已有的 `txt_list` 和 `mapping`。
    - 使用 BeautifulSoup 解析 HTML 页面以获取电视剧信息。
    - 对于隐藏的剧集，会通过额外的 API 请求获取播放源信息。
    """

    global txt_list
    if len(txt_list) > 0:
        txt_list = []
        mapping.clear()

    # 设置请求头，模拟浏览器访问腾讯视频
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/103.0.0.0 Safari/537.36',
        'referer': 'https://v.qq.com/'
    }
    # 构建搜索 URL 并获取页面内容
    url = f'https://v.qq.com/x/search/?q={query}'
    html_content = requests.get(url, headers=headers, verify=False).content.decode('utf-8')
    parser = BeautifulSoup(html_content, 'html.parser')

    # 查找包含剧集信息的主容器
    root_div = parser.find('div', attrs={'class': 'result_episode_list'})
    if root_div is not None:
        # 获取第一个剧集链接的 dt-params，用于提取电视剧名称
        link_urls = root_div.find_all('a', attrs={'dt-eid': 'poster'})
        expand_link = root_div.find('a', attrs={'dt-eid': 'expand_btn'})
        movie_name = link_urls[0].get('dt-params').split('&')[0].split('=')[-1]

        def handler_hide_url(ele_link):
            """
            解析隐藏剧集链接的 dt-params，获取播放源信息。

            参数:
            - ele_link: bs4.element.Tag, 包含隐藏剧集信息的 HTML 元素。

            返回值:
            - json_data: list, 包含播放源信息的 JSON 数据列表。
            """
            v_id = None
            site = None
            page_num = None
            detail = ele_link.get('dt-params')
            for p in detail.split('&'):
                if 'cid' in p:
                    v_id = p.split('=')[-1]
                if 'site_id' in p:
                    site = p.split('=')[-1]
                if 'pg_num' in p:
                    page_num = p.split('=')[-1]

            # 设置请求所需的 cookies 和 headers
            cookies = {
                '_pcmgr_localtk': '9QgVb6(74L',
                '_qpsvr_localtk': 'O)6kvwidDd',
                'pgv_info': 'ssid=s3912331901',
                'pgv_pvid': '4948984288',
                'tvfe_boss_uuid': '78adf163dd9d6537',
                'video_platform': '2',
                'video_guid': '991b6533a95a6b2b',
            }
            headers = {
                'authority': 'pbaccess.video.qq.com',
                'origin': 'https://v.qq.com',
                'referer': 'https://v.qq.com/',
                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
            }
            # 构建请求参数
            # 初始化请求参数

            params = {
                'pageNum': page_num,  # 页码
                'id': v_id,  # 视频ID
                'dataType': '2',  # 数据类型，此处固定为3
                'pageContext': 'need_async=true',  # 页面上下文，此处指定异步请求
                'scene': '2',  # 场景标识，此处固定为2
                'platform': '2',  # 平台标识，此处固定为2
                'appId': '10718',  # 应用ID，此处固定为10718
                'site': site,  # 站点ID，根据实际情况配置
                'vappid': '34382579',  # 视频应用ID，此处固定为34382579
                'vsecret': 'e496b057758aeb04b3a2d623c952a1c47e04ffb0a01e19cf',  # 视频应用密钥，此处固定
            }
            # 发送请求获取播放源信息
            detail_url = 'https://pbaccess.video.qq.com/trpc.videosearch.search_cgi.http/load_playsource_list_info'
            response = requests.get(detail_url, params=params, cookies=cookies, headers=headers)
            # 解析 JSON 数据并返回播放源信息
            return response.json()['data']['normalList']['itemList'][0]['videoInfo']['firstBlockSites'][0][
                'episodeInfoList']

        # 如果存在隐藏的剧集，处理隐藏的剧集链接
        if expand_link is not None:
            movie_detail = handler_hide_url(expand_link)
        else:
            # 如果没有隐藏的剧集，处理可见的剧集链接
            movie_detail = [{'url': url.get('href'), 'title':index +  1} for index, url in enumerate(link_urls)]

        # 将剧集信息（标题和链接）添加到 `txt_list` 和 `mapping`
        for item in movie_detail:
            play_url = item['url']  # 提取播放链接
            current_index = item['title']  # 提取当前集数的标题
            full_url = f'{line}?url={play_url}'  # 构造完整播放链接
            title = f'【{movie_name}】第{current_index}集'  # 生成视频标题
            mapping[title] = full_url  # 将视频标题和播放链接映射起来
            txt_list.append(title)  # 将视频标题添加到列表中，可能用于后续输出或处理

    else:
        # 若未找到对应电视剧，输出提示信息
        print(f'未找到与"{query}"匹配的电视剧')


def fetch_movie_url(query, line=None):
    """
    根据查询词获取电影链接

    参数:
    - query: 查询词，用于搜索电影的关键字
    - line: 行号（可选），用于生成电影链接的标识

    返回值:
    无返回值，但会更新全局变量`txt_list`和`mapping`。
    `txt_list`存储电影名称，`mapping`存储电影名称与完整URL的映射。
    """
    global txt_list
    if len(txt_list) > 0:
        # 如果txt_list非空，则清空列表和mapping
        txt_list = []
        mapping.clear()

    # 设置请求头，伪装为Chrome浏览器访问
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
        'referer': 'https://v.qq.com/'
    }
    # 构造搜索URL
    url = f'https://v.qq.com/x/search/?q={query}'
    # 发起GET请求，获取HTML内容
    html_content = requests.get(url, headers=headers, verify=False).content.decode('utf-8')
    # 使用BeautifulSoup解析HTML
    parser = BeautifulSoup(html_content, 'html.parser')
    # 查找结果按钮行
    root_div = parser.find('div', attrs={'class': 'result_btn_line'})
    if root_div is not None:
        # 在结果按钮行中查找链接项
        link_item = root_div.find('a')
        # 提取播放链接和电影名称
        play_url = link_item.get('href')
        detail = link_item.get('dt-params')
        movie_name = detail.split('&')[0].split('=')[-1]
        # 生成完整的电影链接并更新mapping和txt_list
        full_url = f'{line}?url={play_url}'
        mapping[movie_name] = full_url
        txt_list.append(movie_name)

    else:
        # 如果未找到对应的电影，打印提示信息
        print(f'未找到{query}对应的电影')


def fetch_tv_show_url(query, line=None):
    """
    根据给定的关键词 `query` 在腾讯视频网站上搜索电视剧，并获取其播放链接 URL。

    参数:
    - query: str - 搜索关键词。
    - line: str - 用于格式化输出的行前缀，默认为 None，表示无前缀。

    全局变量:
    - txt_list: list - 存储电视剧名称的列表。
    - mapping: dict - 键为电视剧名称，值为完整的播放链接 URL 的字典。

    返回:
    - 无返回值，但会更新全局变量 `txt_list` 和 `mapping`。
    """

    global txt_list
    # 清空已有的数据
    if len(txt_list) > 0:
        txt_list = []
        mapping.clear()

    # 设置请求头以模拟浏览器访问
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/103.0.0.0 Safari/537.36',
        'referer': 'https://v.qq.com/'
    }
    # 构造搜索 URL 并发送请求
    url = f'https://v.qq.com/x/search/?q={query}'
    html_content = requests.get(url, headers=headers, verify=False).content.decode('utf-8')
    parser = BeautifulSoup(html_content, 'html.parser')

    # 解析 HTML，获取电影详情
    root_div = parser.find('div', attrs={'class': 'result_link_list'})
    movie_detail = []
    if root_div is not None:
        # 处理页面上可见的链接
        link_urls = root_div.find_all('a', attrs={'dt-eid': 'poster'})
        expand_link = root_div.find('a', attrs={'dt-eid': 'expand_btn'})
        for url in link_urls:
            movie_obj = {
                'url': url.get('href'),
                'title': url.get('title')
            }
            movie_detail.append(movie_obj)

        def handler_hide_url(ele_link, index):
            """
            处理腾讯视频隐藏URL的函数，用于获取视频详细信息。

            参数:
            - ele_link: 字典类型，包含视频链接的参数，如'dt-params'。
            - index: 整数类型，表示要获取的视频详情页码。

            返回值:
            - json_data: 列表类型，包含从腾讯视频服务器获取的视频详细信息。
            """

            # 初始化变量v_id和site为None，用于存储视频ID和站点ID
            v_id = None
            site = None

            # 从ele_link的'dt-params'字段中提取视频ID和站点ID
            detail = ele_link.get('dt-params')
            for param in detail.split('&'):
                if 'cid' in param:
                    # 使用split()方法获取视频ID
                    v_id = param.split('=')[-1]
                elif 'site_id' in param:
                    # 使用split()方法获取站点ID
                    site = param.split('=')[-1]

            # 定义请求所需的cookies
            cookies = {
                'tvfe_boss_uuid': '24c539ba5cc5db67',
                'pgv_pvid': '4341653816',
                'video_platform': '2',
                'video_guid': 'f721a570554a868a',
                'pgv_info': 'ssid=s8973242302',
                'vversion_name': '8.2.95',
                'video_omgid': 'f721a570554a868a',
            }

            # 定义请求头信息，包括来源、用户代理等
            headers = {
                'authority': 'pbaccess.video.qq.com',
                'origin': 'https://v.qq.com',
                'referer': 'https://v.qq.com/',
                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
            }

            # 构建请求参数，包括页码、视频ID、站点ID等
            params = {
                'pageNum': index,
                'id': v_id,
                'dataType': '3',
                'pageContext': 'need_async=true&offset_begin=5',
                'scene': '3',
                'platform': '2',
                'appId': '10718',
                'site': site,
                'vappid': '34382579',
                'vsecret': 'e496b057758aeb04b3a2d623c952a1c47e04ffb0a01e19cf',
                'g_tk': '',
                'g_vstk': '',
                'g_actk': '',
            }

            # 定义请求的URL，用于获取视频详细信息
            detail_url = 'https://pbaccess.video.qq.com/trpc.videosearch.search_cgi.http/load_playsource_list_info'

            # 发送GET请求并获取JSON响应
            response = requests.get(detail_url, params=params, cookies=cookies, headers=headers)

            # 解析JSON响应，提取所需视频详细信息
            res_json = response.json()
            json_data = res_json['data']['normalList']['itemList'][0]['videoInfo']['firstBlockSites'][0][
                'episodeInfoList']

            # 返回视频详细信息列表
            return json_data

        # 处理隐藏的链接
        if expand_link is not None:
            load_all = False
            current_index = 0
            while not load_all:
                result_data = handler_hide_url(expand_link, current_index)
                current_index += 1
                last_data = result_data[-1]
                for movie in result_data:
                    if str(movie.get('displayType')) == '0':
                        movie_obj = {
                            'url': movie.get('url'),
                            'title': movie.get('title')
                        }
                        movie_detail.append(movie_obj)
                if str(last_data.get('displayType')) == '0':
                    load_all = True

        # 格式化和存储结果
        for item in movie_detail:
            play_url = item['url']
            title = item['title']
            full_url = f'{line}?url={play_url}' if line else play_url
            mapping[title] = full_url
            txt_list.append(title)
    else:
        print(f'在腾讯视频上未找到与"{query}"相关的电视剧')

    # 输出结果
    for title in txt_list:
        print(f'找到电视剧：{title}')


# 创建一个Tkinter窗口，用于vip视频解析选择和搜索
window = tk.Tk()

# 创建解析通道标签并放置在窗口的第二行
label3 = tk.Label(window, text="解析通道")
label3.grid(row=2)

# 定义可选择的解析线路及其URL
site = [('线路一', 'https://jx.aidouer.net/'),
        ('线路二', r'D:\Program Files (x86)\PotPlayer\PotPlayerMini64.exe'),
        ('线路三', 'https://jx.blbo.cc:4433/')]

# 创建并设置一个StringVar，用于存储选择的解析线路
site_v = tk.StringVar()

# 为每一条解析线路创建一个RadioButton，并将其添加到窗口中
site_radio_01 = tk.Radiobutton(window, text=site[0][0], variable=site_v, value=site[0][1])
site_radio_01.grid(row=2, column=1)
site_radio_01.select()

site_radio_02 = tk.Radiobutton(window, text=site[1][0], variable=site_v, value=site[1][1])
site_radio_02.grid(row=2, column=2)

site_radio_03 = tk.Radiobutton(window, text=site[2][0], variable=site_v, value=site[2][1])
site_radio_03.grid(row=2, column=3)

# 创建搜索类别标签并放置在窗口的第三行
label3 = tk.Label(window, text="搜索类别")
label3.grid(row=3)

# 定义可选择的搜索类别及其标识
search_type = [('电视剧', '1'), ('电影', '2'), ('综艺', '3')]

# 创建并设置一个StringVar，用于存储选择的搜索类别
search_v = tk.StringVar()

# 为每一种搜索类别创建一个RadioButton，并将其添加到窗口中
type_radio_01 = tk.Radiobutton(window, text=search_type[0][0], variable=search_v, value=search_type[0][1])
type_radio_01.grid(row=3, column=1)
type_radio_01.select()

type_radio_02 = tk.Radiobutton(window, text=search_type[1][0], variable=search_v, value=search_type[1][1])
type_radio_02.grid(row=3, column=2)

type_radio_03 = tk.Radiobutton(window, text=search_type[2][0], variable=search_v, value=search_type[2][1])
type_radio_03.grid(row=3, column=3)

# 创建搜索方式相关标签和选项，放置在窗口的第三行和第四行
label3 = tk.Label(window, text="搜索方式")
label3.grid(row=3)

op_type = [('搜索', 'search'), ('链接', 'link')]
label4 = tk.Label(window, text="搜索类型")
label4.grid(row=4)

# 创建并设置一个StringVar，用于存储选择的搜索方式
op_v = tk.StringVar()

# 为每一种搜索方式创建一个RadioButton，并将其添加到窗口中
op_radio_01 = tk.Radiobutton(window, text=op_type[0][0], variable=op_v, value=op_type[0][1])
op_radio_01.grid(row=4, column=1)
op_radio_01.select()

op_radio_02 = tk.Radiobutton(window, text=op_type[1][0], variable=op_v, value=op_type[1][1])
op_radio_02.grid(row=4, column=2)

# 调整窗口大小和位置，并设置窗口标题
center_window(window, 520, 200)
window.title("爬个视频")
window.resizable(0, 0)

# 创建视频名称标签和输入框，放置在窗口的第五行
query_label = tk.Label(window, text="视频名称")
query_label.grid(row=5)

query_v = tk.StringVar()
query_input = tk.Entry(window, textvariable=query_v)
query_input.grid(row=5, column=1)

# 创建搜索按钮，点击后执行搜索操作
search_btn = tk.Button(window, text='搜索', command=do_search)
search_btn.grid(row=7, column=2)

# 创建显示搜索结果的标签，放置在窗口的第六行
result_label = tk.Label(window, text="搜索结果")
result_label.grid(row=6)

# 创建一个只读的组合框，用于显示搜索结果
cbox = ttk.Combobox(window, state='readonly')
cbox.grid(row=6, column=1)

# 创建播放按钮，点击后执行播放视频操作
play_btn = tk.Button(window, text='播放', command=play_video)
play_btn.grid(row=7, column=3)

# 运行窗口的主循环
window.mainloop()

